/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package imp.gestores;
import imp.clases.*;
import java.util.ArrayList;
import java.util.List;


/**
 *
 * @author Angelical
 */
public class GestorOrganigrama {

    List<Linea> lineas;
    List<Cargo> listaCargos;
    List<Cargo> colaCargos;

    String datosMatriz[][];


    public GestorOrganigrama(){
    this.lineas= new ArrayList<Linea>();
    this.listaCargos= new ArrayList<Cargo>();
    this.colaCargos=new ArrayList<Cargo>();
    
    //Inicio los valores de la matriz
    datosMatriz=new String[15][15];
    }

    public void addLinea(Linea l){
    lineas.add(l);
    }
    public void removeLinea(Linea l){
    lineas.remove(l);
    }

    public List<Linea> getLineas() {
        return lineas;
    }

    public void setLineas(List<Linea> lineas) {
        this.lineas = lineas;
    }

    public List<Cargo> getListaCargos() {
        return listaCargos;
    }

    public void setListaCargos(List<Cargo> listaCargos) {
        this.listaCargos = listaCargos;
    }



    public void generarColaCargo(){
        //Ordenar la lista inicial en funcion de su nivel:
        ordenarPorNivel();

        //encero la matriz:
        datosMatriz=new String[15][15];
        //Proceso de Ordenamiento de la lista de Cargos Obtenidos:
        int tamanoLista=this.listaCargos.size();

        //Encero la cola de Cargos
        this.colaCargos.clear();
        for(int n=0;n<tamanoLista;n++){
            //Saco el cargo actual:
            Cargo cargoActual=this.listaCargos.get(n);
            List<Cargo> cargoRelacionados=buscarRelaciones(cargoActual);
            adjuntoCola(cargoActual,cargoRelacionados);

        }
        //Acabo generando la cola de cargos.
        
        //Cargo los datos en la matriz:
        cargoMatriz();
        

        //Coloco las lineas de los graficos del organigrama:
        colocarLineas();
        //Paso de matriz a lineas
        pasoMaLineas();

     
    }


    public void colocarLineas(){
    int tamano=this.datosMatriz.length;
        for(int filas=1;filas<tamano;filas=filas+2){

            int numCargos=cantFila[filas];
            //Recorro las columnas:
            for(int columnas=0;columnas<tamano;columnas++){
                boolean padre=sacoPadre(filas,columnas);
                boolean hijo=sacoHijo(filas,columnas);
                int hijoSobran=sacoHijosS(filas,columnas);

                //Programo la logica de muestreo  ############


                if(padre){
                    if(hijo){
                        if(hijoSobran>1){
                            //Pongo (2)
                            this.datosMatriz[filas][columnas]="2";
                        }else{
                            //Pongo (1)
                            this.datosMatriz[filas][columnas]="1";
                        }
                    }else{
                        //No se pone nada en este caso;
                    }
                }else{
                    if(hijo){
                        if(hijoSobran>1){
                            //Pongo (4)
                            this.datosMatriz[filas][columnas]="4";

                        }else{
                            //Pongo (3)
                            this.datosMatriz[filas][columnas]="3";

                        }


                    }else{
                        if(hijoSobran>=1){
                            //Pongo (5)
                            this.datosMatriz[filas][columnas]="5";

                        }else{
                            //Pongo (3)
                            this.datosMatriz[filas][columnas]="";

                        }
                        


                    }


                }




                //Programo la Logica del Algoritmo############
            }

        }
    }


    public boolean sacoPadre(int x, int y){

        try {
            if (datosMatriz[x - 1][y].length() > 3) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
    }

    public boolean sacoHijo(int x, int y) {
        try {
            if (datosMatriz[x + 1][y].length() > 3) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }

    }

    public int sacoHijosS(int x, int y) {
        int tamano = this.datosMatriz.length;
        int contador = 0;
        int contadorPadre = 0;
        for (int n = y; n < tamano; n++) {
            if (sacoPadre(x, n)) {
                contadorPadre++;
            }
            
            if(n==y)
            {
             if(sacoPadre(x,n)){
             
             }else{
                 contadorPadre=1;
             }
            }


            if (contadorPadre <= 1) {
                try {
                    if (datosMatriz[x + 1][n].length() > 3) {
                        contador++;
                    }
                } catch (Exception e) {
                }
            } else {
                break;
            }
        }
        return contador;
    }



    public void pasoMaLineas(){
        int tamano=datosMatriz.length;
        lineas.clear();
        for(int n=0;n<tamano;n++){

            Linea linea =new Linea();
            linea.setValor1(datosMatriz[n][0]);
            linea.setValor2(datosMatriz[n][1]);
            linea.setValor3(datosMatriz[n][2]);
            linea.setValor4(datosMatriz[n][3]);
            linea.setValor5(datosMatriz[n][4]);
            linea.setValor6(datosMatriz[n][5]);
            linea.setValor7(datosMatriz[n][6]);
            linea.setValor8(datosMatriz[n][7]);
            linea.setValor9(datosMatriz[n][8]);
            linea.setValor10(datosMatriz[n][9]);
            linea.setValor11(datosMatriz[n][10]);
            linea.setValor12(datosMatriz[n][11]);
            linea.setValor13(datosMatriz[n][12]);
            linea.setValor14(datosMatriz[n][13]);
            linea.setValor15(datosMatriz[n][14]);

            lineas.add(linea);

        }



    }



    int[] cantFila;
    public void cargoMatriz(){
    //Cargo los datos en la matriz:
    int tamano=this.colaCargos.size();
    cantFila=new int[15];
    punterocol=0;
        
        for(int n=0;n<tamano;n++){
            Cargo cargo=this.colaCargos.get(n);
            int fila=cargo.getNivel()*2;
            int columna=this.buscoExtFondo(fila);

            //validoColumna
            columna=valido(columna);

            datosMatriz[fila][columna]=cargo.getDescripcion();
            cantFila[fila]=cantFila[fila]+1;
            punterocol=columna;


        }

    }

    int punterocol;
    public int valido(int col){
     //Comparo para que nunca la nueva columna se
     //menor a la anterior
        if(punterocol>col) {
        col=punterocol;
        }
    return col;
    }

    public void encero(int[] lista){
        int tamano=lista.length;
        for(int n=0;n<tamano;n++){
        lista[n]=0;
        }
    }


   
    int[] cantExten;
    public int buscoExtFondo(int nivel){
        //Lleno del vector:
        cantExten=new int [15];
        cantExten=llenarExtensiones(cantExten);

        //cantFila
        int tamano=cantExten.length;
        int mayor=0;
        for(int n=nivel;n<tamano-1;n++){
          if(n==nivel){
            if(cantExten[n]>cantExten[n+1]){
            mayor=cantExten[n];
            }else{
            mayor=cantExten[n+1];
            }
          }else{
            if(mayor>cantExten[n+1]){
            }else{
            mayor=cantExten[n+1];
            }

          }

        }

        //Encontrado el la extension del fondo
        return mayor;

    }



    public int[] llenarExtensiones(int[] extesionFilas){
        int tamano=datosMatriz.length;

        for(int filas=0;filas<tamano;filas++){
            int mayor=0;
            for(int column=0;column<tamano;column++){

              try{
                if(datosMatriz[filas][column].length()>3){
               mayor=column+1;
                }
              }catch(Exception e){}
              
            }
        extesionFilas[filas]=mayor;
        }
        return extesionFilas;
    }


    List<Cargo> colaTemporal;

    public void adjuntoCola(Cargo cargoActual,List<Cargo> cargoRelacionados){
    boolean encontro=false;
    int codigoPadre=cargoActual.getCodigo();
    colaTemporal=new ArrayList<Cargo>();
    int posInsertCola=-1;

        //Busco Cargo Actual en la colaCargos
        int largo=colaCargos.size();

        for(int n=0;n<largo;n++){
            Cargo cargo=this.colaCargos.get(n);
            int codigoHijo=cargo.getCodigo();

            //Pregunto si existe padre en la cola cargos
            if(codigoPadre==codigoHijo){
            encontro=true;
            posInsertCola=n;
            break;
            }

        }
        //Si encontro le adjunto a la cola:
        if(encontro){
            //Adjunto a la cola anterior a la relacion:

            for(int n=0;n<posInsertCola+1;n++){

                this.colaTemporal.add(this.colaCargos.get(n));
            }

            //Adjuntar los Relacionados
            int largoR=cargoRelacionados.size();
            for(int n=0;n<largoR;n++){

                this.colaTemporal.add(cargoRelacionados.get(n));
            }

            //Adjuntar los de la cola posterior a la relacion
            int tamano=this.colaCargos.size();
            for(int n=(posInsertCola+1);n<tamano;n++){
                this.colaTemporal.add(this.colaCargos.get(n));
            }

            //Pongo la cola Temporal a la cola Real
            this.colaCargos=this.colaTemporal;


        }else{
        //En el caso que no encuentre le adjunto al final de la lista al
            this.colaCargos.add(cargoActual);
            
            //Agrego los Relacionados.
            for(int n=0;n<cargoRelacionados.size();n++){
            this.colaCargos.add(cargoRelacionados.get(n));
            }

        }





    }

    public List<Cargo> buscarRelaciones(Cargo c){
    List<Cargo> cargoHijos=new ArrayList<Cargo>();

    //Saco codigo de Padre
      int codigoPadre=c.getCodigo();


        int tamanoLista=this.listaCargos.size();

        for(int n=0;n<tamanoLista;n++){
            Cargo cargo=this.listaCargos.get(n);
            //Verifico sus Cargos Dependientes:
            int dependeDe=cargo.getDepende_de();
            //Pregunto si depende o no?
            if(codigoPadre==dependeDe){
            cargoHijos.add(cargo);

            }


        }
    return cargoHijos;
    }



    public void ordenarPorNivel(){
        //listo la ordenada
        List<Cargo> listaOrdenada=new ArrayList<Cargo>();
        java.util.Collections.sort(this.listaCargos);

    }



}
